home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / engrave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  24.7 KB  |  879 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)engrave.c    3.1    92/06/16    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "lev.h"
  7. #include <ctype.h>
  8.  
  9. STATIC_VAR NEARDATA struct engr *head_engr;
  10.  
  11. STATIC_DCL void FDECL(del_engr, (struct engr *));
  12.  
  13. #ifdef OVLB
  14. /* random engravings */
  15. const char *random_mesg[] = {
  16.     "Elbereth", "ad ae?ar um",
  17.     "?la? ?as he??",
  18.     /* take-offs and other famous engravings */
  19.     "Owlbreath", "?ala??iel",
  20.     "?ilroy wa? h?re",
  21.     "A.S. ->", "<- A.S.", /* Journey to the Center of the Earth */
  22.     "Y?u won t get i? up ?he ste?s", /* Adventure */
  23.     "Lasc?ate o?ni sp?ranz? o vo? c?'en?rate", /* Inferno */
  24.     "Well Come", /* Prisoner */
  25.     "W? ap?l???ze for t?e inc?nve??e?ce", /* So Long... */
  26.     "S?e you n?xt Wed?esd?y", /* Thriller */
  27.     "Fo? a ?ood time c?ll 8?7-53?9",
  28. };
  29.  
  30. const char *
  31. random_engraving()
  32. {
  33.     char *rumor, *s;
  34.  
  35. /* a random engraving may come from the "rumors" file, or from the
  36.    list above */
  37.     rumor = getrumor(0);
  38.     if (rn2(4) && *rumor) {
  39.         for (s = rumor; *s; s++)
  40.             if (!rn2(7) && *s != ' ') *s = '?';
  41.         if (s[-1] == '.') s[-1] = 0;
  42.         return (const char *)rumor;
  43.     }
  44.     else
  45.         return random_mesg[rn2(SIZE(random_mesg))];
  46. }
  47. #endif /* OVLB */
  48. #ifdef OVL0
  49.  
  50. const char *
  51. surface(x, y)
  52. register int x, y;
  53. {
  54.     register struct rm *lev = &levl[x][y];
  55.  
  56.     if (IS_AIR(lev->typ))
  57.         return "air";
  58.     else if (is_pool(x,y))
  59.         return "water";
  60.     else if (is_ice(x,y))
  61.         return "ice";
  62.     else if (is_lava(x,y))
  63.         return "lava";
  64.     else if (lev->typ == DRAWBRIDGE_DOWN)
  65.         return "bridge";
  66.     else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) ||
  67.          IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR)
  68.         return "floor";
  69.     else
  70.         return "ground";
  71. }
  72.  
  73. struct engr *
  74. engr_at(x,y) register xchar x,y; {
  75. register struct engr *ep = head_engr;
  76.     while(ep) {
  77.         if(x == ep->engr_x && y == ep->engr_y)
  78.             return(ep);
  79.         ep = ep->nxt_engr;
  80.     }
  81.     return((struct engr *) 0);
  82. }
  83.  
  84. #ifdef ELBERETH
  85. int
  86. sengr_at(s,x,y)
  87.     register const char *s;
  88.     register xchar x,y;
  89. {
  90.     register struct engr *ep = engr_at(x,y);
  91.     register char *t;
  92.     register int n;
  93.  
  94.     if(ep && ep->engr_time <= moves) {
  95.         t = ep->engr_txt;
  96. /*
  97.         if(!strcmp(s,t)) return(1);
  98. */
  99.         n = strlen(s);
  100.         while(*t) {
  101.             if(!strncmp(s,t,n)) return(1);
  102.             t++;
  103.         }
  104.     }
  105.     return(0);
  106. }
  107. #endif
  108.  
  109. #endif /* OVL0 */
  110. #ifdef OVL2
  111.  
  112. void
  113. u_wipe_engr(cnt)
  114. register int cnt;
  115. {
  116.     if(!u.uswallow && !Levitation)
  117.         wipe_engr_at(u.ux, u.uy, cnt);
  118. }
  119.  
  120. #endif /* OVL2 */
  121. #ifdef OVL1
  122.  
  123. void
  124. wipe_engr_at(x,y,cnt) register xchar x,y,cnt; {
  125. register struct engr *ep = engr_at(x,y);
  126. register int lth,pos;
  127. char ch;
  128.     if(ep){
  129.         if(ep->engr_type != BURN) {
  130.         if(ep->engr_type != DUST && ep->engr_type != BLOOD) {
  131.             cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1;
  132.         }
  133.         lth = strlen(ep->engr_txt);
  134.         if(lth && cnt > 0 ) {
  135.             while(cnt--) {
  136.                 pos = rn2(lth);
  137.                 if((ch = ep->engr_txt[pos]) == ' ')
  138.                     continue;
  139.                 ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
  140.             }
  141.         }
  142.         while(lth && ep->engr_txt[lth-1] == ' ')
  143.             ep->engr_txt[--lth] = 0;
  144.         while(ep->engr_txt[0] == ' ')
  145.             ep->engr_txt++;
  146.         if(!ep->engr_txt[0]) del_engr(ep);
  147.         }
  148.     }
  149. }
  150.  
  151. #endif /* OVL1 */
  152. #ifdef OVL2
  153.  
  154. void
  155. read_engr_at(x,y)
  156. register int x,y;
  157. {
  158.     register struct engr *ep = engr_at(x,y);
  159.     register int    sensed = 0;
  160.  
  161.     if(ep && ep->engr_txt[0]) {
  162.         switch(ep->engr_type) {
  163.         case DUST:
  164.         if(!Blind) {
  165.             sensed = 1;
  166.             pline("Something is written here in the %s.",
  167.                 is_ice(x,y) ? "frost" : "dust");
  168.         }
  169.         break;
  170.         case ENGRAVE:
  171.         if(!Blind || !Levitation) {
  172.             sensed = 1;
  173.             pline("Something is engraved here on the %s.",
  174.                 surface(x,y));
  175.         }
  176.         break;
  177.         case BURN:
  178.         if(!Blind || !Levitation) {
  179.             sensed = 1;
  180.             pline("Some text has been %s into the %s here.",
  181.                 is_ice(x,y) ? "melted" : "burned",
  182.                 surface(x,y));
  183.         }
  184.         break;
  185.         case MARK:
  186.         if(!Blind) {
  187.             sensed = 1;
  188.             pline("There's some graffiti on the %s here.",
  189.                 surface(x,y));
  190.         }
  191.         break;
  192.         case BLOOD:
  193.         /* "It's a message!  Scrawled in blood!"
  194.          * "What's it say?"
  195.          * "It says... `See you next Wednesday.'" -- Thriller
  196.          */
  197.         if(!Blind) {
  198.             sensed = 1;
  199.             You("see a message scrawled in blood here.");
  200.         }
  201.         break;
  202.         default:
  203.         impossible("Something is written in a very strange way.");
  204.         sensed = 1;
  205.         }
  206.         if (sensed) {
  207.         You("%s: \"%s\".",
  208.               (Blind) ? "feel the words" : "read",  ep->engr_txt);
  209.         if(flags.run > 1) nomul(0);
  210.         }
  211.     }
  212. }
  213.  
  214. #endif /* OVL2 */
  215. #ifdef OVLB
  216.  
  217. void
  218. make_engr_at(x,y,s,e_time,e_type)
  219. register int x,y;
  220. register const char *s;
  221. register long e_time;
  222. register xchar e_type;
  223. {
  224.     register struct engr *ep;
  225.  
  226.     if ((ep = engr_at(x,y)) != 0)
  227.         del_engr(ep);
  228.     ep = newengr(strlen(s) + 1);
  229.     ep->nxt_engr = head_engr;
  230.     head_engr = ep;
  231.     ep->engr_x = x;
  232.     ep->engr_y = y;
  233.     ep->engr_txt = (char *)(ep + 1);
  234.     Strcpy(ep->engr_txt, s);
  235.     if(strcmp(s, "Elbereth")) exercise(A_WIS, TRUE);
  236.     ep->engr_time = e_time;
  237.     ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE);
  238.     ep->engr_lth = strlen(s) + 1;
  239. }
  240.  
  241. /* delete any engraving at location <x,y> */
  242. void
  243. del_engr_at(x, y)
  244. int x, y;
  245. {
  246.     register struct engr *ep = engr_at(x, y);
  247.  
  248.     if (ep) del_engr(ep);
  249. }
  250.  
  251. /*
  252.  *    freehand - returns true if player has a free hand
  253.  */
  254. int
  255. freehand()
  256. {
  257.     return(!uwep || !welded(uwep) ||
  258.        (!bimanual(uwep) && (!uarms || !uarms->cursed)));
  259. /*    if ((uwep && bimanual(uwep)) ||
  260.         (uwep && uarms))
  261.         return(0);
  262.     else
  263.         return(1);*/
  264. }
  265.  
  266. static NEARDATA const char styluses[] =
  267.     { ALL_CLASSES, ALLOW_NONE, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS,
  268.       GEM_CLASS, RING_CLASS, 0 };
  269.  
  270. /* Mohs' Hardness Scale:
  271.  *  1 - Talc         6 - Orthoclase
  272.  *  2 - Gypsum         7 - Quartz
  273.  *  3 - Calcite         8 - Topaz
  274.  *  4 - Fluorite     9 - Corundum
  275.  *  5 - Apatite        10 - Diamond
  276.  *
  277.  * Since granite is a igneous rock hardness ~ 7, anything >= 8 should
  278.  * probably be able to scratch the rock.
  279.  * Devaluation of less hard gems is not easily possible because obj struct
  280.  * does not contain individual oc_cost currently. 7/91
  281.  *
  282.  * dilithium  - ??            * jade        -  5-6    (nephrite)
  283.  * diamond    - 10            * turquoise -  5-6
  284.  * ruby          -  9    (corundum)    * opal        -  5-6
  285.  * sapphire   -  9    (corundum)    * iron        -  4-5
  286.  * topaz      -  8            * fluorite  -  4
  287.  * emerald    -  7.5-8    (beryl)        * brass     -  3-4
  288.  * aquamarine -  7.5-8    (beryl)        * gold        -  2.5-3
  289.  * garnet     -  7.25    (var. 6.5-8)    * silver    -  2.5-3
  290.  * agate      -  7    (quartz)    * copper    -  2.5-3
  291.  * amethyst   -  7    (quartz)    * amber     -  2-2.5
  292.  * jasper     -  7    (quartz)    *    
  293.  * onyx          -  7     (quartz)    * steel     -  5-8.5    (usu. weapon)
  294.  * moonstone  -  6    (orthoclase)    *
  295.  */
  296.  
  297. static NEARDATA const short hard_gems[] =
  298.     { DIAMOND, RUBY, SAPPHIRE, TOPAZ, EMERALD, AQUAMARINE, GARNET, 0 };
  299.  
  300. static NEARDATA const char *hard_ring_names[] =
  301.     {"diamond", "ruby", "sapphire", "emerald", "topaz", ""};
  302.  
  303. /* return 1 if action took 1 (or more) moves, 0 if error or aborted */
  304. int
  305. doengrave()
  306. {
  307.     boolean dengr = FALSE;    /* TRUE if we wipe out the current engraving */
  308.     boolean doblind = FALSE;/* TRUE if engraving blinds the player */
  309.     boolean doknown = FALSE;/* TRUE if we identify the stylus */
  310.     boolean eow = FALSE;    /* TRUE if we are overwriting oep */
  311.     boolean jello = FALSE;    /* TRUE if we are engraving in slime */
  312.     boolean ptext = TRUE;    /* TRUE if we must prompt for engrave text */
  313.     boolean teleengr =FALSE;/* TRUE if we move the old engraving */
  314.     boolean zapwand = FALSE;/* TRUE if we remove a wand charge */
  315.     xchar type = DUST;    /* Type of engraving made */
  316.     char buf[BUFSZ];    /* Buffer for final/poly engraving text */
  317.     char ebuf[BUFSZ];    /* Buffer for initial engraving text */
  318.     char qbuf[QBUFSZ];    /* Buffer for query text */
  319.     char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */
  320.     const char *everb;    /* Present tense of engraving type */
  321.     const char *eloc;    /* Where the engraving is (ie dust/floor/...) */
  322.     register char *sp;    /* Place holder for space count of engr text */
  323.     register int len;    /* # of nonspace chars of new engraving text */
  324.     register int maxelen;    /* Max allowable length of new engraving text */
  325.     register int spct;    /* # of spaces in new engraving text */
  326.     register struct engr *oep = engr_at(u.ux,u.uy);
  327.                 /* The current engraving */
  328.     register struct obj *otmp; /* Object selected with which to engrave */
  329.  
  330.  
  331.     multi = 0;        /* moves consumed */
  332.     nomovemsg = (char *)0;    /* occupation end message */
  333.  
  334.     buf[0] = (char)0;
  335.     ebuf[0] = (char)0;
  336.     post_engr_text[0] = (char)0;
  337.     maxelen = BUFSZ - 1;
  338.  
  339.     /* Can the adventurer engrave at all? */
  340.  
  341.     if(u.uswallow) {
  342.         if (is_animal(u.ustuck->data)) {
  343.             pline("What would you write?  \"Jonah was here\"?");
  344.             return(0);
  345.         } else if (is_whirly(u.ustuck->data)) {
  346.             You("can't reach the %s.", surface(u.ux,u.uy));
  347.             return(0);
  348.         } else 
  349.             jello = TRUE;
  350.     } else if (is_lava(u.ux, u.uy)) {
  351.         You("can't write on the lava!");
  352.         return(0);
  353.     } else if (is_pool(u.ux,u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
  354.         You("can't write on the water!");
  355.         return(0);
  356.     }
  357.     if(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)/* in bubble */) {
  358.         You("can't write in thin air!");
  359.         return(0);
  360.     }
  361. #ifdef POLYSELF
  362.     if (cantwield(uasmon)) {
  363.         You("can't even hold anything!");
  364.         return(0);
  365.     }
  366. #endif
  367.     if (check_capacity(NULL)) return (0);
  368.  
  369.     /* One may write with finger, or weapon, or wand, or..., or...
  370.      * Edited by GAN 10/20/86 so as not to change weapon wielded.
  371.      */
  372.  
  373.     otmp = getobj(styluses, "write with");
  374.     if(!otmp) return(0);        /* otmp == zeroobj if fingers */
  375.  
  376.     /* There's no reason you should be able to write with a wand
  377.      * while both your hands are tied up.
  378.      */
  379.     if (!freehand() && otmp != uwep && !otmp->owornmask) {
  380.         You("have no free %s to write with!", body_part(HAND));
  381.         return(0);
  382.     }
  383.  
  384.     if (jello) {
  385.         You("tickle %s with your %s.", mon_nam(u.ustuck), 
  386.             (otmp == &zeroobj) ? makeplural(body_part(FINGER)) :
  387.             xname(otmp));
  388.         Your("message dissolves...");
  389.         return(0);
  390.     }
  391.     if(Levitation && otmp->oclass != WAND_CLASS){        /* riv05!a3 */
  392.         You("can't reach the %s!", surface(u.ux,u.uy));
  393.         return(0);
  394.     }
  395.  
  396.     /* SPFX for items */
  397.  
  398.     switch (otmp->oclass) {
  399.         default:
  400.         case AMULET_CLASS:
  401.         case CHAIN_CLASS:
  402.         case POTION_CLASS:
  403.         case GOLD_CLASS:
  404.         break;
  405.  
  406.         case RING_CLASS:
  407.         /* "diamond" rings and others should work */
  408.         {
  409.             register int i, j;
  410.  
  411.             for (i=0, j=strlen(hard_ring_names[i]); j; i++)
  412.             if ( !strncmp(hard_ring_names[i],
  413.                  OBJ_DESCR(objects[otmp->otyp]),
  414.                  j=strlen(hard_ring_names[i])) ) {
  415.                 type = ENGRAVE;
  416.                 break;
  417.             }
  418.         }
  419.         break;
  420.  
  421.         case GEM_CLASS:
  422.         /* diamonds & other gems should work */
  423.         {
  424.             register int i;
  425.  
  426.             for (i=0; hard_gems[i]; i++)
  427.             if (otmp->otyp == hard_gems[i]) {
  428.                 type = ENGRAVE;
  429.                 break;
  430.             }
  431.         }
  432.         break;
  433.  
  434.         /* Objects too large to engrave with */
  435.         case BALL_CLASS:
  436.         case ROCK_CLASS:
  437.         case ARMOR_CLASS:
  438.         You("can't engrave with such a large object!");
  439.         ptext = FALSE;
  440.         break;
  441.  
  442.         /* Objects too silly to engrave with */
  443.         case FOOD_CLASS:
  444.         case SCROLL_CLASS:
  445.         case SPBOOK_CLASS:
  446.         Your("%s would get %s.", xname(otmp),
  447.             is_ice(u.ux,u.uy) ? "all frosty" : "too dirty");
  448.         ptext = FALSE;
  449.         break;
  450.  
  451.         case RANDOM_CLASS:    /* This should mean fingers */
  452.         break;
  453.  
  454.         /* The charge is removed from the wand before prompting for
  455.          * the engraving text, because all kinds of setup decisions
  456.          * and pre-engraving messages are based upon knowing what type
  457.          * of engraving the wand is going to do.  Also, the player
  458.          * will have potentially seen "You wrest .." message, and
  459.          * therefore will know they are using a charge.
  460.          */
  461.         case WAND_CLASS:
  462.         if (zappable(otmp)) {
  463.             check_unpaid(otmp);
  464.             zapwand = TRUE;
  465.             if (Levitation) ptext = FALSE;
  466.  
  467.             switch (otmp->otyp) {
  468.             /* DUST wands */
  469.             default:
  470.             break;
  471.  
  472.             /* NODIR wands */
  473.             case WAN_LIGHT:
  474.             case WAN_SECRET_DOOR_DETECTION:
  475.             case WAN_CREATE_MONSTER:
  476.             case WAN_WISHING:
  477.               zapnodir(otmp);
  478.             break;
  479.  
  480.             /* IMMEDIATE wands */
  481.                 /* If wand is "IMMEDIATE", remember to affect the
  482.              * previous engraving even if turning to dust.
  483.              */
  484.             case WAN_STRIKING:
  485.             Strcpy(post_engr_text,
  486.             "The wand unsuccessfully fights your attempt to write!"
  487.             );
  488.             break;
  489.             case WAN_SLOW_MONSTER:
  490.             if (!Blind) {
  491.                Sprintf(post_engr_text,
  492.                    "The bugs on the %s slow down!",
  493.                    surface(u.ux, u.uy));
  494.             }
  495.             break;
  496.             case WAN_SPEED_MONSTER:
  497.             if (!Blind) {
  498.                Sprintf(post_engr_text,
  499.                    "The bugs on the %s speed up!",
  500.                    surface(u.ux, u.uy));
  501.             }
  502.             break;
  503.             case WAN_POLYMORPH:
  504.             if(oep)  {
  505.                 if (!Blind) {
  506.                 type = (xchar)0;    /* random */
  507.                 Strcpy(buf,random_engraving());
  508.                 }
  509.                 dengr = TRUE;
  510.             }
  511.             break;
  512.             case WAN_NOTHING:
  513.             case WAN_UNDEAD_TURNING:
  514.             case WAN_OPENING:
  515.             case WAN_LOCKING:
  516.             case WAN_PROBING:
  517.             break;
  518.  
  519.             /* RAY wands */
  520.             case WAN_MAGIC_MISSILE:
  521.             ptext = TRUE;
  522.             if (!Blind) {
  523.                Sprintf(post_engr_text,
  524.                    "The %s is riddled by bullet holes!",
  525.                    surface(u.ux, u.uy));
  526.             }
  527.             break;
  528.  
  529.             /* can't tell sleep from death - Eric Backus */
  530.             case WAN_SLEEP:
  531.             case WAN_DEATH:
  532.             if (!Blind) {
  533.                Sprintf(post_engr_text,
  534.                    "The bugs on the %s stop moving!",
  535.                    surface(u.ux, u.uy));
  536.             }
  537.             break;
  538.  
  539.             case WAN_COLD:
  540.             if (!Blind)
  541.                 Strcpy(post_engr_text,
  542.                 "A few ice cubes drop from the wand.");
  543.             if(!oep || (oep->engr_type != BURN))
  544.                 break;
  545.             case WAN_CANCELLATION:
  546.             case WAN_MAKE_INVISIBLE:
  547.             if(oep) {
  548.                 if (!Blind)
  549.                 pline("The engraving on the %s vanishes!",
  550.                     surface(u.ux,u.uy));
  551.                 dengr = TRUE;
  552.             }
  553.             break;
  554.             case WAN_TELEPORTATION:
  555.             if (oep) {
  556.                 if (!Blind)
  557.                 pline("The engraving on the %s vanishes!",
  558.                     surface(u.ux,u.uy));
  559.                 teleengr = TRUE;
  560.             }
  561.             break;
  562.  
  563.             /* type = ENGRAVE wands */
  564.             case WAN_DIGGING:
  565.             ptext = TRUE;
  566.             type  = ENGRAVE;
  567.             if(!objects[otmp->otyp].oc_name_known) {
  568.                     if (flags.verbose)
  569.                 pline("This %s is a wand of digging!",
  570.                 xname(otmp));
  571.                 doknown = TRUE;
  572.             }
  573.             if (!Blind)
  574.                 Strcpy(post_engr_text,
  575.                 is_ice(u.ux,u.uy) ? 
  576.                 "Ice chips fly up from the ice surface!" :
  577.                     "Gravel flies up from the floor.");
  578.             else
  579.                 Strcpy(post_engr_text, "You hear drilling!");
  580.             break;
  581.  
  582.             /* type = BURN wands */
  583.             case WAN_FIRE:
  584.             ptext = TRUE;
  585.             type  = BURN;
  586.             if(!objects[otmp->otyp].oc_name_known) {
  587.                 if (flags.verbose)
  588.                 pline("This %s is a wand of fire!", xname(otmp));
  589.                 doknown = TRUE;
  590.             }
  591.             Strcpy(post_engr_text,
  592.                 Blind ? "You feel the wand heat up." :
  593.                     "Flames fly from the wand.");
  594.             break;
  595.             case WAN_LIGHTNING:
  596.             ptext = TRUE;
  597.             type  = BURN;
  598.             if(!objects[otmp->otyp].oc_name_known) {
  599.                     if (flags.verbose)
  600.                 pline("This %s is a wand of lightning!",
  601.                     xname(otmp));
  602.                 doknown = TRUE;
  603.             }
  604.             if (!Blind) {
  605.                 Strcpy(post_engr_text,
  606.                     "Lightning arcs from the wand.");
  607.                 doblind = TRUE;
  608.             } else
  609.                 Strcpy(post_engr_text, "You hear crackling!");
  610.             break;
  611.  
  612.             /* type = MARK wands */
  613.             /* type = BLOOD wands */
  614.             }
  615.         } else /* end if zappable */
  616.             if (Levitation) {
  617.             You("can't reach the %s!", surface(u.ux,u.uy));
  618.             return(0);
  619.             }
  620.         break;
  621.  
  622.         case WEAPON_CLASS:
  623.         if(is_blade(otmp))
  624.             if ((int)otmp->spe > -3)
  625.             type = ENGRAVE;
  626.             else
  627.             Your("%s too dull for engraving.", aobjnam(otmp,"are"));
  628.         break;
  629.  
  630.         case TOOL_CLASS:
  631.         if(otmp == ublindf) {
  632.             pline(
  633.         "That is a bit difficult to engrave with, don't you think?");
  634.             return(0);
  635.         }
  636.         switch (otmp->otyp)  {
  637.             case MAGIC_MARKER:
  638.             if (otmp->spe <= 0)
  639.                 Your("marker has dried out.");
  640.             else
  641.                 type = MARK;
  642.             break;
  643.             case TOWEL:
  644.              /* Can't really engrave with a towel */
  645.             ptext = FALSE;
  646.             if (oep)
  647.                 if ((oep->engr_type == DUST ) ||
  648.                 (oep->engr_type == BLOOD) ||
  649.                 (oep->engr_type == MARK )) {
  650.                 if (!Blind)
  651.                     You("wipe out the message here.");
  652.                 else
  653.                     Your("%s gets %s.", xname(otmp),
  654.                       is_ice(u.ux,u.uy) ?
  655.                       "frosty" : "dusty");
  656.                 dengr = TRUE;
  657.                 } else
  658.                 Your("%s can't wipe out this engraving.",
  659.                      xname(otmp));
  660.             else
  661.                 Your("%s gets %s.", xname(otmp),
  662.                   is_ice(u.ux,u.uy) ? "frosty" : "dusty");
  663.             break;
  664.             default:
  665.             break;
  666.         }
  667.         break;
  668.  
  669.         case VENOM_CLASS:
  670. #ifdef WIZARD
  671.         if (wizard) {
  672.             pline("Writing a poison pen letter??");
  673.             break;
  674.         }
  675. #endif
  676.         case ILLOBJ_CLASS:
  677.         impossible("You're engraving with an illegal object!");
  678.         break;
  679.     }
  680.  
  681.     /* End of implement setup */
  682.  
  683.     /* Identify stylus */
  684.     if (doknown) {
  685.         makeknown(otmp->otyp);
  686.         more_experienced(0,10);
  687.     }
  688.  
  689.     if (teleengr) {
  690.         register int tx,ty;
  691.  
  692.         do  {
  693.          tx = rn1(COLNO-3,2);
  694.         ty = rn2(ROWNO);
  695.         } while(!goodpos(tx,ty, (struct monst *)0, (struct permonst *)0));
  696.  
  697.         oep->engr_x urn(0);
  698.         }
  699.     }
  700.  
  701.     len -= spct;
  702.  
  703.     /* Previous engraving is overwritten */
  704.     if (eow) {
  705.         del_engr(oep);
  706.         oep = (struct engr *)0;
  707.     }
  708.  
  709.     /* Figure out how long it took to engrave, and if player has
  710.      * engraved too much.
  711.      */
  712.     switch(type){
  713.         default:
  714.         multi = -(len/10);
  715.         if (multi) nomovemsg = "You finish your weird engraving.";
  716.         break;
  717.         case DUST:
  718.         multi = -(len/10);
  719.         if (multi) nomovemsg = "You finish writing in the dust.";
  720.         break;
  721.         case ENGRAVE:
  722.         multi = -(len/10);
  723.         if ((otmp->oclass == WEAPON_CLASS) &&
  724.             ((otmp->otyp != ATHAME) || otmp->cursed)) {
  725.             multi = -len;
  726.             maxelen = ((otmp->spe + 3) * 2) + 1;
  727.             /* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11
  728.              * Note: this does not allow a +0 anything (except
  729.              *     an athame) to engrave "Elbereth" all at once.
  730.              *     However, you could now engrave "Elb", then
  731.              *     "ere", then "th".
  732.              */
  733.             Your("%s dull.", aobjnam(otmp, "get"));
  734.             if (len > maxelen) {
  735.                 multi = -maxelen;
  736.             otmp->spe = -3;
  737.             } else
  738.             if (len > 1) otmp->spe -= len >> 1;
  739.             else otmp->spe -= 1; /* Prevent infinite engraving */
  740.         } else
  741.             if ( (otmp->oclass == RING_CLASS) ||
  742.              (otmp->oclass == GEM_CLASS) )
  743.             multi = -len;
  744.         if (multi) nomovemsg = "You finish engraving.";
  745.         break;
  746.         case BURN:
  747.         multi = -(len/10);
  748.         if (multi)
  749.             nomovemsg = is_ice(u.ux,u.uy) ?
  750.             "You finish melting your message into the ice.":
  751.             "You finish burning your message into the floor.";
  752.         break;
  753.         case MARK:
  754.         multi = -(len/10);
  755.         if ((otmp->oclass == TOOL_CLASS) &&
  756.             (otmp->otyp == MAGIC_MARKER)) {
  757.             maxelen = (otmp->spe) * 2; /* one charge / 2 letters */
  758.             if (len > maxelen) {
  759.             Your("marker dries out.");
  760.             otmp->spe = 0;
  761.             multi = -(maxelen/10);
  762.             } else
  763.             if (len > 1) otmp->spe -= len >> 1;
  764.             else otmp->spe -= 1; /* Prevent infinite grafitti */
  765.         }
  766.         if (multi) nomovemsg = "You finish defacing the dungeon.";
  767.         break;
  768.         case BLOOD:
  769.         multi = -(len/10);
  770.         if (multi) nomovemsg = "You finish scrawling.";
  771.         break;
  772.     }
  773.  
  774.     /* Chop engraving down to size if necessary */
  775.     if (len > maxelen) {
  776.         for (sp = ebuf; (maxelen && *sp); sp++)
  777.         if (!isspace(*sp)) maxelen--;
  778.         if (!maxelen && *sp) {
  779.         *sp = (char)0;
  780.         if (multi) nomovemsg = "You cannot write any more.";
  781.         You("only are able to write \"%s\"", ebuf);
  782.         }
  783.     }
  784.  
  785.     /* Add to existing engraving */
  786.     if (oep) Strcpy(buf, oep->engr_txt);    
  787.  
  788.     (void) strncat(buf, ebuf, (BUFSZ - (int)strlen(buf) - 1));
  789.  
  790.     make_engr_at(u.ux, u.uy, buf, (moves - multi), type);
  791.  
  792.     if (post_engr_text[0]) pline(post_engr_text);
  793.  
  794.     if (doblind) {
  795.         You("are blinded by the flash!");
  796.         make_blinded((long)rnd(50),FALSE);
  797.     }
  798.  
  799.     return(1);
  800. }
  801.  
  802. void
  803. save_engravings(fd, mode)
  804. int fd, mode;
  805. {
  806.     register struct engr *ep = head_engr;
  807.     register struct engr *ep2;
  808. #ifdef GCC_WARN
  809.     static long nulls[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  810. #endif
  811.     while(ep) {
  812.         ep2 = ep->nxt_engr;
  813.         if(ep->engr_lth && ep->engr_txt[0]){
  814.         bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth));
  815.         bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth);
  816.         }
  817.         if (mode & FREE_SAVE)
  818.         dealloc_engr(ep);
  819.         ep = ep2;
  820.     }
  821.  
  822. #ifdef GCC_WARN
  823.     bwrite(fd, (genericptr_t)nulls, sizeof(unsigned));
  824. #else
  825.     bwrite(fd, (genericptr_t)nul, sizeof(unsigned));
  826. #endif
  827.  
  828.     if (mode & FREE_SAVE)
  829.         head_engr = 0;
  830. }
  831.  
  832. void
  833. rest_engravings(fd)
  834. int fd;
  835. {
  836. register struct engr *ep;
  837. unsigned lth;
  838.     head_engr = 0;
  839.     while(1) {
  840.         mread(fd, (genericptr_t) <h, sizeof(unsigned));
  841.         if(lth == 0) return;
  842.         ep = newengr(lth);
  843.         mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth);
  844.         ep->nxt_engr = head_engr;
  845.         head_engr = ep;
  846.         ep->engr_txt = (char *) (ep + 1);    /* Andreas Bormann */
  847.         /* mark as finished for bones levels -- no problem for
  848.          * normal levels as the player must have finished engraving
  849.          * to be able to move again */
  850.         ep->engr_time = moves;
  851.     }
  852. }
  853.  
  854. STATIC_OVL void
  855. del_engr(ep)
  856. register struct engr *ep;
  857. {
  858.     if (ep == head_engr) {
  859.         head_engr = ep->nxt_engr;
  860.     } else {
  861.         register struct engr *ept;
  862.  
  863.         for (ept = head_engr; ept; ept = ept->nxt_engr)
  864.             if (ept->nxt_engr == ep) {
  865.             ept->nxt_engr = ep->nxt_engr;
  866.             break;
  867.             }
  868.         if (!ept) {
  869.             impossible("Error in del_engr?");
  870.             return;
  871.         }
  872.     }
  873.     dealloc_engr(ep);
  874. }
  875.  
  876. #endif /* OVLB */
  877.  
  878. /*engrave.c*/
  879.